package utils

import (
	"errors"
	"github.com/dgrijalva/jwt-go"
	"penguin/model"
	"penguin/penguin"
	"penguin/response"
	"time"
)

var tokenKey = []byte("USjqT1UmUkeId1jS9UXhCdG0194OSK")

func SignToken(uid string, nickName string, admin bool) (tokenString string, err error) {
	timeNow := time.Now()
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"uid":       uid,
		"nick_name": nickName,
		"admin":     admin,
		"nbf":       timeNow.Unix(),
		"exp":       timeNow.Add(penguin.TokenDuration).Unix(),
	})
	tokenString, err = token.SignedString(tokenKey)
	return
}

func ValidateToken(tokenInfo *response.TokenInfo) (user model.User, valid bool) {
	token, err := jwt.Parse(tokenInfo.Token, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, errors.New("parse token failed")
		}
		return tokenKey, nil
	})
	if err != nil {
		return
	}
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		uid, ok := claims["uid"]
		if !ok {
			return
		}
		exp, ok := claims["exp"]
		if !ok {
			return
		}
		nickName, ok := claims["nick_name"]
		if !ok {
			return
		}
		admin, ok := claims["admin"]
		if !ok {
			return
		}
		uidString, ok := uid.(string)
		if !ok {
			return
		}
		expFloat64, ok := exp.(float64)
		if !ok {
			return
		}
		expInt64 := int64(expFloat64)
		if uidString != tokenInfo.Uid {
			return
		}
		if time.Now().Unix() > expInt64 {
			return
		}
		nickNameString, ok := nickName.(string)
		if !ok {
			return
		}
		adminBool, ok := admin.(bool)
		if !ok {
			return
		}
		user.Uid = uidString
		user.NickName = nickNameString
		user.Admin = adminBool
		valid = true
	} else {
		return
	}
	return
}
